'## Copyright (c) 2011, Hacker Wez under the New BSD License, see glyphx-license.txt (http://glyphx.codeplex.com/)
Imports SdlDotNet.Windows
Imports SdlDotNet.Graphics
Imports SdlDotNet.Core
Public Class canvasForm


    ' # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 
    ' # # # variables
    ' # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 

    Dim rng As New Random                           '// our god object
    Dim footprints As New List(Of footprint)        '// list of glyphs and their footprints
    Dim glyphs As New List(Of glyph)

    Dim glyphmap As Surface                         '// the glyphmap we draw our symbols from
    Dim background As Surface                       '// static background
    Dim buffer As Surface                           '// buffer we render on and send to the sdl surface each tick
    Dim canvas As SurfaceControl                    '// our sdl canvas
    Dim canvas_width As Integer                     '// our canvas size


    ' # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 
    ' # # # properties
    ' # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 


    Public Property background_Color() As Drawing.Color
        Get
            Return _Background_Color
        End Get
        Set(ByVal value As Drawing.Color)
            _Background_Color = value
            background.Fill(value)
        End Set
    End Property
    Private _Background_Color As Drawing.Color = Color.Black


    Public Property Trails() As Boolean
        Get
            Return _Trails
        End Get
        Set(ByVal value As Boolean)
            _Trails = value
        End Set
    End Property
    Private _Trails As Boolean


    Public Property Orientation() As Windows.Forms.SortOrder
        Get
            Return _Orientation
        End Get
        Set(ByVal value As Windows.Forms.SortOrder)
            _Orientation = value
        End Set
    End Property
    Private _Orientation As Windows.Forms.SortOrder

    Public Property Max_onscreen_glyphs() As Integer
        Get
            Return _Max_onscreen_glyphs
        End Get
        Set(ByVal value As Integer)
            _Max_onscreen_glyphs = value
        End Set
    End Property
    Private _Max_onscreen_glyphs As Integer







    ' # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 
    ' # # # functions
    ' # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 

    '// setup the sdl canvas control to paint on
    Sub setup_canvas()
        SdlDotNet.Core.Events.TargetFps = FPS
        canvas = New SdlDotNet.Windows.SurfaceControl
        canvas.Width = Me.Width
        canvas.Height = Me.Height
        canvas.Region = New Region(Me.ClientRectangle)
        canvas.BackColor = Color.Black
        Me.Controls.Add(canvas)
    End Sub

    '// setup the background used to clear the canvas
    Sub setup_background()
        background = New Surface(canvas.Width, canvas.Height)
        background.Fill(background_Color)
    End Sub

    '// setup the buffer we draw to the canvas
    Sub setup_buffer()
        buffer = New Surface(canvas.Width, canvas.Height)
    End Sub

    '// setup the window size and position
    Sub setup_screen_size()
        canvas_width = Windows.Forms.Screen.PrimaryScreen.Bounds.Width
        Me.Width = canvas_width
        Me.Height = CANVAS_HEIGHT
        Me.Left = 0
        If (Orientation = SortOrder.Ascending) Then
            Me.Top = 0
        Else
            Me.Top = Screen.PrimaryScreen.Bounds.Height - CANVAS_HEIGHT
        End If
    End Sub

    '// setup the glyph map and create the first glyphs
    Sub setup_glyphmap()
        Max_onscreen_glyphs = 25
        glyphmap = New Surface(My.Resources.glyphmap)
        For idx As Integer = 1 To Max_onscreen_glyphs
            glyphs.Add(create_glyph)
        Next
    End Sub

    '// setup the ui window
    Sub setup_window()
        Me.Text = My.Application.Info.ProductName
        Me.ShowInTaskbar = False
    End Sub

    '// setup sdl engine handlers
    Sub setup_handlers()
        AddHandler SdlDotNet.Core.Events.Tick, AddressOf Tick
        SdlDotNet.Core.Events.Run()
    End Sub

    '// create a new glyph
    Function create_glyph() As glyph
        Dim g As New glyph
        g.X = rng.Next(canvas_width)
        g.Y = -GLYPH_SPRITE_SIZE
        g.Speed = rng.Next(GLYPH_SPEED_MIN, GLYPH_SPEED_MAX)
        g.Volatility = rng.Next(RNG_MIN, RNG_MAX) \ GLYPH_MORPH_RATIO
        g.Index = rng.Next(GLYPHMAP_ITEMS)
        g.Decay = rng.Next(GLYPH_DECAY_MIN, GLYPH_DECAY_MAX)
        Return g
    End Function

    '// potentially mutate the glyph into another one, and update the position if not a footprint
    Sub mutate_glyph(ByVal g As glyph)
        Dim dice As Integer = 0
        dice = rng.Next(RNG_MIN, RNG_MAX)
        If (g.Volatility > dice) Then g.Index = rng.Next(GLYPHMAP_ITEMS)

        If (Trails) Then
            Dim item As footprint = g.spawn_footprint
            If Not IsNothing(item) Then footprints.Add(item)
        End If
    End Sub


    ' # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 
    ' # # # events
    ' # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 

    '// entry point
    Private Sub canvasForm_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        setup_screen_size()
        setup_canvas()
        setup_background()
        setup_buffer()
        setup_glyphmap()
        setup_window()
        setup_handlers()
    End Sub

    '// halt sdl core when we close
    Private Sub canvasForm_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
        SdlDotNet.Core.Events.QuitApplication()
    End Sub

    '// paint our canvas
    Sub Tick(ByVal sender As Object, ByVal e As TickEventArgs)

        buffer.Erase(New Rectangle(0, 0, canvas_width, CANVAS_HEIGHT), background)

        ' footprints
        For idx As Integer = 0 To footprints.Count - 1
            If (idx < footprints.Count) Then
                Dim f As footprint = footprints(idx)
                If f.IsAlive Then
                    'blit
                    buffer.Blit(glyphmap, f.ToDestPoint, f.ToBlurSourceRect)
                Else
                    footprints.RemoveAt(idx)
                    idx -= 1    'rerun this last loop
                End If
            End If
        Next

        'glyphs
        For idx As Integer = 0 To glyphs.Count - 1
            If (idx < glyphs.Count) Then
                Dim g As glyph = glyphs(idx)
                mutate_glyph(g)
                g.Y += g.Speed
                ' blur
                buffer.Blit(glyphmap, g.ToDestPoint, g.ToBlurSourceRect)
                ' glyph
                buffer.Blit(glyphmap, g.ToDestPoint, g.ToSourceRect)
                'kill
                If (g.Y > CANVAS_HEIGHT) Then
                    glyphs.RemoveAt(idx)
                    idx -= 1
                    'born again
                    While (glyphs.Count < Max_onscreen_glyphs)
                        glyphs.Add(create_glyph)
                    End While
                End If
            End If
        Next

        canvas.Blit(buffer)
        canvas.Update()

    End Sub

    '// reseat our position if the user moves or sizes their task bar
    Private Sub canvasForm_LocationChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.LocationChanged
        setup_screen_size()
    End Sub

End Class